home *** CD-ROM | disk | FTP | other *** search
/ The Very Best of Atari Inside / The Very Best of Atari Inside 1.iso / mint / mint99s / fasttext.c < prev    next >
C/C++ Source or Header  |  1992-12-23  |  25KB  |  1,301 lines

  1. /*
  2. Copyright 1992,1992 Eric R. Smith.
  3. Copyright 1992 Atari Corporation.
  4. All rights reserved.
  5. */
  6.  
  7. #include "mint.h"
  8. #include "fasttext.h"
  9.  
  10. #ifdef FASTTEXT
  11.  
  12. #ifdef __GNUC__
  13. #define INLINE inline
  14. #define ITYPE long    /* gcc's optimizer likes 32 bit integers */
  15. #else
  16. #define INLINE
  17. #define ITYPE int
  18. #endif
  19.  
  20. #define CONDEV    (2)
  21.  
  22. static SCREEN *current;
  23.  
  24. static void paint P_((SCREEN *, int, char *)),
  25.      paint8c P_((SCREEN *, int, char *)),
  26.      paint16m P_((SCREEN *, int, char *));
  27.  
  28. INLINE static void curs_off P_((SCREEN *)), curs_on P_((SCREEN *));
  29. INLINE static void flash P_((SCREEN *));
  30. static void normal_putch P_((SCREEN *, int));
  31. static void escy_putch P_((SCREEN *, int));
  32. static void quote_putch P_((SCREEN *, int));
  33.  
  34. static    char *chartab[256];
  35.  
  36. #define MAX_PLANES 8
  37. static int fgmask[MAX_PLANES], bgmask[MAX_PLANES];
  38.  
  39. static long scrnsize;
  40.  
  41. short hardscroll;
  42. static char *hardbase, *oldbase;
  43.  
  44. typedef void (*Vfunc) P_((SCREEN *, int));
  45.  
  46. #define base *((char **)0x44eL)
  47. #define escy1 *((short *)0x4acL)
  48.  
  49. static Vfunc state;
  50.  
  51. static short hardline;
  52. static void (*vpaint) P_((SCREEN *, int, char *));
  53.  
  54. void init P_((void));
  55. void hardware_scroll P_((SCREEN *));
  56. INLINE static char *PLACE P_((SCREEN *, int, int));
  57. INLINE static void gotoxy P_((SCREEN *, int, int));
  58. INLINE static void clrline P_((SCREEN *, int));
  59. INLINE static void clear P_((SCREEN *));
  60. INLINE static void clrchar P_((SCREEN *, int, int));
  61. INLINE static void clrfrom P_((SCREEN *, int, int, int, int));
  62. INLINE static void delete_line P_((SCREEN *, int));
  63. INLINE static void insert_line P_((SCREEN *, int));
  64. static void setbgcol P_((SCREEN *, int));
  65. static void setfgcol P_((SCREEN *, int));
  66. static void putesc P_((SCREEN *, int));
  67. static void escy1_putch P_((SCREEN *, int));
  68. INLINE static void put_ch P_((SCREEN *, int));
  69.  
  70. /* routines for flashing the cursor for screen v */
  71. /* flash(v): invert the character currently under the cursor */
  72.  
  73. INLINE static void
  74. flash(v)
  75.     SCREEN *v;
  76. {
  77.     char *place;
  78.     ITYPE i, j, vplanes;
  79.  
  80.     vplanes = v->planes + v->planes;
  81.     place = v->cursaddr;
  82.  
  83.     for (j = v->cheight; j > 0; --j) {
  84.         for (i = 0; i < vplanes; i+=2)
  85.             place[i] = ~place[i];
  86.  
  87.         place += v->planesiz;
  88.     }
  89.     v->curstimer = v->period;
  90. }
  91.  
  92. /* make sure the cursor is off */
  93.  
  94. INLINE
  95. static void
  96. curs_off(v)
  97.     SCREEN *v;
  98. {
  99.     if (v->flags & CURS_ON) {
  100.         if (v->flags & CURS_FSTATE) {
  101.             flash(v);
  102.             v->flags &= ~CURS_FSTATE;
  103.         }
  104.     }
  105. }
  106.  
  107. /* OK, show the cursor again (if appropriate) */
  108.  
  109. INLINE static void
  110. curs_on(v)
  111.     SCREEN *v;
  112. {
  113.     if (v->hidecnt) return;
  114.  
  115.     if (v->flags & CURS_ON) {
  116. #if 0
  117.     /* if the cursor is flashing, we cheat a little and leave it off
  118.      * to be turned on again (if necessary) by the VBL routine
  119.      */
  120.         if (v->flags & CURS_FLASH) {
  121.             v->curstimer = 2;
  122.             return;
  123.         }
  124. #endif
  125.         if (!(v->flags & CURS_FSTATE)) {
  126.             v->flags |= CURS_FSTATE;
  127.             flash(v);
  128.         }
  129.     }
  130. }
  131.  
  132. void
  133. init()
  134. {
  135.     SCREEN *v;
  136.     int i, j;
  137.     char *data, *foo;
  138.     static char chardata[256*16];
  139.  
  140.     foo = lineA0();
  141.     v = (SCREEN *)(foo - 346);
  142.     
  143.     /* Ehem... The screen might be bigger than 32767 bytes.
  144.        Let's do some casting... 
  145.        Erling
  146.     */
  147.     scrnsize = (v->maxy+1)*(long)v->linelen;
  148.     if (hardscroll == -1) {
  149.     /* request for auto-setting */
  150.         hardscroll = v->maxy+1;
  151.     }
  152.     if (hardscroll > 0) {
  153.         if (!hardbase)
  154.             hardbase = (char *)(((long)kcore(SCNSIZE(v)+256L)+255L)
  155.                        & 0xffffff00L);
  156.  
  157.         if (hardbase == 0) {
  158.             ALERT("Insufficient memory for hardware scrolling!");
  159.         } else {
  160.             quickmove(hardbase, base, scrnsize);
  161.             v->cursaddr = v->cursaddr + (hardbase - base);
  162.             oldbase = base;
  163.             base = hardbase;
  164.             Setscreen(hardbase, hardbase, -1);
  165.         }
  166.     }
  167.     hardline = 0;
  168.     if (v->cheight == 8 && v->planes == 2) {
  169.         foo = &chardata[0];
  170.         vpaint = paint8c;
  171.         for (i = 0; i < 256; i++) {
  172.             chartab[i] = foo;
  173.             data = v->fontdata + i;
  174.             for (j = 0; j < 8; j++) {
  175.                 *foo++ = *data;
  176.                 data += v->form_width;
  177.             }
  178.         }
  179.     } else if (v->cheight == 16 && v->planes == 1) {
  180.         foo = &chardata[0];
  181.         vpaint = paint16m;
  182.         for (i = 0; i < 256; i++) {
  183.             chartab[i] = foo;
  184.             data = v->fontdata + i;
  185.             for (j = 0; j < 16; j++) {
  186.                 *foo++ = *data;
  187.                 data += v->form_width;
  188.             }
  189.         }
  190.     }
  191.     else
  192.         vpaint = paint;
  193.  
  194.     if (v->hidecnt == 0) {
  195.     /*
  196.      * make sure the cursor is set up correctly and turned on
  197.      */
  198.         (void)Cursconf(0,0);    /* turn cursor off */
  199.  
  200.         v->flags &= ~CURS_FSTATE;
  201.  
  202.     /* now turn the cursor on the way we like it */
  203.         v->hidecnt = 0;
  204.         curs_on(v);
  205.     } else {
  206.         (void)Cursconf(0,0);
  207.         v->flags &= ~CURS_ON;
  208.         v->hidecnt = 1;
  209.     }
  210.  
  211.     current = v;
  212.     /* setup bgmask and fgmask */
  213.     setbgcol(v, v->bgcol);
  214.     setfgcol(v, v->fgcol);
  215.     state = normal_putch;
  216. }
  217.  
  218. /*
  219.  * PLACE(v, x, y): the address corresponding to the upper left hand corner of
  220.  * the character at position (x,y) on screen v
  221.  */
  222. INLINE static
  223. char *PLACE(v, x, y)
  224.     SCREEN *v;
  225.     int x, y;
  226. {
  227.     char *place;
  228.     int i, j;
  229.  
  230.     place = base + x;
  231.     if (y == v->maxy)
  232.         place += scrnsize - v->linelen;
  233.     else if (y) /* Yo, the screen might be bigger than 32767 bytes...
  234.                Do a cast to long.    Erling. */
  235.         place += (long)y * v->linelen;
  236.  
  237.     if ((j = v->planes) > 1) {
  238.         i = (x & 0xfffe);
  239.         while (--j > 0)
  240.             place += i;
  241.     }
  242.     return place;
  243. }
  244.  
  245. /*
  246.  * paint(v, c, place): put character 'c' at position 'place' on screen
  247.  * v. It is assumed that x, y are proper coordinates!
  248.  * Specialized versions (paint8c and paint16m) of this routine follow;
  249.  * they assume 8 line high characters, medium res. and 16 line/mono,
  250.  * respectively.
  251.  */
  252.  
  253. static void
  254. paint(v, c, place)
  255.     SCREEN *v;
  256.     int c;
  257.     char *place;
  258. {
  259.     char *data, d, doinverse;
  260.     ITYPE j, planecount;
  261.     int vplanes;
  262.     long vform_width, vplanesiz;
  263.  
  264.     vplanes = v->planes;
  265.  
  266.     data = v->fontdata + c;
  267.     doinverse = (v->flags & FINVERSE) ? 0xff : 0;
  268.     vform_width = v->form_width;
  269.     vplanesiz = v->planesiz;
  270.  
  271.     for (j = v->cheight; j > 0; --j) {
  272.         d = *data ^ doinverse;
  273.         for (planecount = 0; planecount < vplanes; planecount++)
  274.           place[planecount << 1]
  275.             = ((d & (char) fgmask[planecount])
  276.                | (~d & (char) bgmask[planecount]));
  277.         place += vplanesiz;
  278.         data += vform_width;
  279.     }
  280. }
  281.  
  282. static void
  283. paint8c(v, c, place)
  284.     SCREEN *v;
  285.     int c;
  286.     char *place;
  287. {
  288.     char *data;
  289.     char d, doinverse;
  290.     char bg0, bg1, fg0, fg1;
  291.     long vplanesiz;
  292.  
  293.     data = chartab[c];
  294.  
  295.     doinverse = (v->flags & FINVERSE) ? 0xff : 0;
  296.     vplanesiz = v->planesiz;
  297.     bg0 = bgmask[0];
  298.     bg1 = bgmask[1];
  299.     fg0 = fgmask[0];
  300.     fg1 = fgmask[1];
  301.  
  302.     if (!doinverse && !bg0 && !bg1 && fg0 && fg1) {
  303.         /* line 1 */
  304.         d = *data++;
  305.         *place = d;
  306.         place[2] = d;
  307.         place += vplanesiz;
  308.  
  309.         /* line 2 */
  310.         d = *data++;
  311.         *place = d;
  312.         place[2] = d;
  313.         place += vplanesiz;
  314.  
  315.         /* line 3 */
  316.         d = *data++;
  317.         *place = d;
  318.         place[2] = d;
  319.         place += vplanesiz;
  320.  
  321.         /* line 4 */
  322.         d = *data++;
  323.         *place = d;
  324.         place[2] = d;
  325.         place += vplanesiz;
  326.  
  327.         /* line 5 */
  328.         d = *data++;
  329.         *place = d;
  330.         place[2] = d;
  331.         place += vplanesiz;
  332.  
  333.         /* line 6 */
  334.         d = *data++;
  335.         *place = d;
  336.         place[2] = d;
  337.         place += vplanesiz;
  338.  
  339.         /* line 7 */
  340.         d = *data++;
  341.         *place = d;
  342.         place[2] = d;
  343.         place += vplanesiz;
  344.  
  345.         /* line 8 */
  346.         d = *data;
  347.         *place = d;
  348.         place[2] = d;
  349.     } else {
  350.         /* line 1 */
  351.         d = *data++ ^ doinverse;
  352.         *place = ((d & fg0) | (~d & bg0));
  353.         place[2] = ((d & fg1) | (~d & bg1));
  354.         place += vplanesiz;
  355.  
  356.         /* line 2 */
  357.         d = *data++ ^ doinverse;
  358.         *place = ((d & fg0) | (~d & bg0));
  359.         place[2] = ((d & fg1) | (~d & bg1));
  360.         place += vplanesiz;
  361.  
  362.         /* line 3 */
  363.         d = *data++ ^ doinverse;
  364.         *place = ((d & fg0) | (~d & bg0));
  365.         place[2] = ((d & fg1) | (~d & bg1));
  366.         place += vplanesiz;
  367.  
  368.         /* line 4 */
  369.         d = *data++ ^ doinverse;
  370.         *place = ((d & fg0) | (~d & bg0));
  371.         place[2] = ((d & fg1) | (~d & bg1));
  372.         place += vplanesiz;
  373.  
  374.         /* line 5 */
  375.         d = *data++ ^ doinverse;
  376.         *place = ((d & fg0) | (~d & bg0));
  377.         place[2] = ((d & fg1) | (~d & bg1));
  378.         place += vplanesiz;
  379.  
  380.         /* line 6 */
  381.         d = *data++ ^ doinverse;
  382.         *place = ((d & fg0) | (~d & bg0));
  383.         place[2] = ((d & fg1) | (~d & bg1));
  384.         place += vplanesiz;
  385.  
  386.         /* line 7 */
  387.         d = *data++ ^ doinverse;
  388.         *place = ((d & fg0) | (~d & bg0));
  389.         place[2] = ((d & fg1) | (~d & bg1));
  390.         place += vplanesiz;
  391.  
  392.         /* line 8 */
  393.         d = *data ^ doinverse;
  394.         *place = ((d & fg0) | (~d & bg0));
  395.         place[2] = ((d & fg1) | (~d & bg1));
  396.     }
  397. }
  398.  
  399. static void
  400. paint16m(v, c, place)
  401.     SCREEN *v;
  402.     int c;
  403.     char *place;
  404. {
  405.     char *data;
  406.     char d, doinverse;
  407.     long vplanesiz;
  408.  
  409.     data = chartab[c];
  410.     doinverse = (v->flags & FINVERSE) ? 0xff : 0;
  411.     doinverse ^= bgmask[0];
  412.     vplanesiz = v->planesiz;
  413.  
  414.     if (bgmask[0] == fgmask[0])
  415.       {
  416.         /* fgcol and bgcol are the same -- easy */
  417.         d = (char) bgmask[0];
  418.         *place = d;
  419.         place += vplanesiz;
  420.         *place = d;
  421.         place += vplanesiz;
  422.         *place = d;
  423.         place += vplanesiz;
  424.         *place = d;
  425.         place += vplanesiz;
  426.         *place = d;
  427.         place += vplanesiz;
  428.         *place = d;
  429.         place += vplanesiz;
  430.         *place = d;
  431.         place += vplanesiz;
  432.         *place = d;
  433.         place += vplanesiz;
  434.         *place = d;
  435.         place += vplanesiz;
  436.         *place = d;
  437.         place += vplanesiz;
  438.         *place = d;
  439.         place += vplanesiz;
  440.         *place = d;
  441.         place += vplanesiz;
  442.         *place = d;
  443.         place += vplanesiz;
  444.         *place = d;
  445.         place += vplanesiz;
  446.         *place = d;
  447.         place += vplanesiz;
  448.         *place = d;
  449.       }
  450.     else if (!doinverse) {
  451.         /* line 1 */
  452.         d = *data++;
  453.         *place = d;
  454.         place += vplanesiz;
  455.  
  456.         /* line 2 */
  457.         d = *data++;
  458.         *place = d;
  459.         place += vplanesiz;
  460.  
  461.         /* line 3 */
  462.         d = *data++;
  463.         *place = d;
  464.         place += vplanesiz;
  465.  
  466.         /* line 4 */
  467.         d = *data++;
  468.         *place = d;
  469.         place += vplanesiz;
  470.  
  471.         /* line 5 */
  472.         d = *data++;
  473.         *place = d;
  474.         place += vplanesiz;
  475.  
  476.         /* line 6 */
  477.         d = *data++;
  478.         *place = d;
  479.         place += vplanesiz;
  480.  
  481.         /* line 7 */
  482.         d = *data++;
  483.         *place = d;
  484.         place += vplanesiz;
  485.  
  486.         /* line 8 */
  487.         d = *data++;
  488.         *place = d;
  489.         place += vplanesiz;
  490.  
  491.         /* line 9 */
  492.         d = *data++;
  493.         *place = d;
  494.         place += vplanesiz;
  495.  
  496.         /* line 10 */
  497.         d = *data++;
  498.         *place = d;
  499.         place += vplanesiz;
  500.  
  501.         /* line 11 */
  502.         d = *data++;
  503.         *place = d;
  504.         place += vplanesiz;
  505.  
  506.         /* line 12 */
  507.         d = *data++;
  508.         *place = d;
  509.         place += vplanesiz;
  510.  
  511.         /* line 13 */
  512.         d = *data++;
  513.         *place = d;
  514.         place += vplanesiz;
  515.  
  516.         /* line 14 */
  517.         d = *data++;
  518.         *place = d;
  519.         place += vplanesiz;
  520.  
  521.         /* line 15 */
  522.         d = *data++;
  523.         *place = d;
  524.         place += vplanesiz;
  525.  
  526.         /* line 16 */
  527.         d = *data;
  528.         *place = d;
  529.     } else {
  530.         /* line 1 */
  531.         d = ~*data++;
  532.         *place = d;
  533.         place += vplanesiz;
  534.  
  535.         /* line 2 */
  536.         d = ~*data++;
  537.         *place = d;
  538.         place += vplanesiz;
  539.  
  540.         /* line 3 */
  541.         d = ~*data++;
  542.         *place = d;
  543.         place += vplanesiz;
  544.  
  545.         /* line 4 */
  546.         d = ~*data++;
  547.         *place = d;
  548.         place += vplanesiz;
  549.  
  550.         /* line 5 */
  551.         d = ~*data++;
  552.         *place = d;
  553.         place += vplanesiz;
  554.  
  555.         /* line 6 */
  556.         d = ~*data++;
  557.         *place = d;
  558.         place += vplanesiz;
  559.  
  560.         /* line 7 */
  561.         d = ~*data++;
  562.         *place = d;
  563.         place += vplanesiz;
  564.  
  565.         /* line 8 */
  566.         d = ~*data++;
  567.         *place = d;
  568.         place += vplanesiz;
  569.  
  570.         /* line 9 */
  571.         d = ~*data++;
  572.         *place = d;
  573.         place += vplanesiz;
  574.  
  575.         /* line 10 */
  576.         d = ~*data++;
  577.         *place = d;
  578.         place += vplanesiz;
  579.  
  580.         /* line 11 */
  581.         d = ~*data++;
  582.         *place = d;
  583.         place += vplanesiz;
  584.  
  585.         /* line 12 */
  586.         d = ~*data++;
  587.         *place = d;
  588.         place += vplanesiz;
  589.  
  590.         /* line 13 */
  591.         d = ~*data++;
  592.         *place = d;
  593.         place += vplanesiz;
  594.  
  595.         /* line 14 */
  596.         d = ~*data++;
  597.         *place = d;
  598.         place += vplanesiz;
  599.  
  600.         /* line 15 */
  601.         d = ~*data++;
  602.         *place = d;
  603.         place += vplanesiz;
  604.  
  605.         /* line 16 */
  606.         d = ~*data;
  607.         *place = d;
  608.     }
  609. }
  610.  
  611. /*
  612.  * gotoxy (v, x, y): move current cursor address of screen v to (x, y)
  613.  * makes sure that (x, y) will be legal
  614.  */
  615.  
  616. INLINE static void
  617. gotoxy(v, x, y)
  618.     SCREEN *v;
  619.     int x, y;
  620. {
  621.     if (x > v->maxx) x = v->maxx;
  622.     else if (x < 0) x = 0;
  623.     if (y > v->maxy) y = v->maxy;
  624.     else if (y < 0) y = 0;
  625.  
  626.     v->cx = x;
  627.     v->cy = y;
  628.     v->cursaddr = PLACE(v, x, y);
  629. }
  630.  
  631. /*
  632.  * clrline(v, r): clear line r of screen v
  633.  */
  634.  
  635. INLINE static void
  636. clrline(v, r)
  637.     SCREEN *v;
  638.     int r;
  639. {
  640.     int *dst, *m;
  641.     long nwords;
  642.     int i, vplanes;
  643.  
  644.     /* Hey, again the screen might be bigger than 32767 bytes.
  645.        Do another cast... */
  646.     dst = (int *)(base + ((long)r * v->linelen));
  647.     if (v->bgcol == 0)
  648.       zero((char *)dst, v->linelen);
  649.     else
  650.       {
  651.         /* do it the hard way */
  652.         vplanes = v->planes;
  653.         for (nwords = v->linelen >> 1; nwords > 0; nwords -= vplanes)
  654.           {
  655.         m = bgmask;
  656.         for (i = 0; i < vplanes; i++)
  657.           *dst++ = *m++;
  658.           }
  659.       }
  660. }
  661.     
  662. /*
  663.  * clear(v): clear the whole screen v
  664.  */
  665.  
  666. INLINE static void
  667. clear(v)
  668.     SCREEN *v;
  669. {
  670.     int i, vplanes;
  671.     int *dst, *m;
  672.     long nwords;
  673.  
  674.     if (v->bgcol == 0)
  675.       zero(base, scrnsize);
  676.     else
  677.       {
  678.         /* do it the hard way */
  679.         dst = (int *) base;
  680.         vplanes = v->planes;
  681.         for (nwords = scrnsize >> 1; nwords > 0; nwords -= vplanes)
  682.           {
  683.         m = bgmask;
  684.         for (i = 0; i < vplanes; i++)
  685.           *dst++ = *m++;
  686.           }
  687.       }
  688. }
  689.  
  690. /*
  691.  * clrchar(v, x, y): clear the (x,y) position on screen v
  692.  */
  693.  
  694. INLINE static void
  695. clrchar(v, x, y)
  696.     SCREEN *v;
  697.     int x, y;
  698. {
  699.     int i, j, vplanes;
  700.     char *place;
  701.     int *m;
  702.  
  703.     vplanes = v->planes + v->planes;
  704.  
  705.     place = PLACE(v, x, y);
  706.  
  707.     for (j = v->cheight; j > 0; --j) {
  708.         m = bgmask;
  709.         for (i = 0; i < vplanes; i += 2)
  710.             place[i] = (char) *m++;
  711.         place += v->planesiz;
  712.     }
  713. }
  714.  
  715. /*
  716.  * clrfrom(v, x1, y1, x2, y2): clear screen v from position (x1,y1) to
  717.  * position (x2, y2) inclusive. It is assumed that y2 >= y1.
  718.  */
  719.  
  720. INLINE static void
  721. clrfrom(v, x1, y1, x2, y2)
  722.     SCREEN *v;
  723.     int x1,y1,x2,y2;
  724. {
  725.     int i;
  726.  
  727.     for (i = x1; i <= v->maxx; i++)
  728.         clrchar(v, i, y1);
  729.     if (y2 > y1) {
  730.         for (i = 0; i <= x2; i++)
  731.             clrchar(v, i, y2);
  732.         for (i = y1+1; i < y2; i++)
  733.             clrline(v, i);
  734.     }
  735. }
  736.  
  737. /*
  738.  * scroll a screen in hardware; if we still have hardware scrolling lines left,
  739.  * just move the physical screen base, otherwise copy the screen back to the
  740.  * hardware base and start over
  741.  */
  742. void
  743. hardware_scroll(v)
  744.     SCREEN *v;
  745. {
  746.  
  747.     ++hardline;
  748.     if (hardline < hardscroll) { /* just move the screen */
  749.         base += v->linelen;
  750.         v->cursaddr = PLACE(v, v->cx, v->cy);
  751.         Setscreen(base, base, -1);
  752.     }
  753.     else {
  754.         hardline = 0;
  755.         quickmove(hardbase, base + v->linelen, scrnsize - v->linelen);
  756.         base = hardbase;
  757.         v->cursaddr = PLACE(v, v->cx, v->cy);
  758.         Setscreen(hardbase, hardbase, -1);
  759.     }
  760. }
  761.  
  762. /*
  763.  * delete_line(v, r): delete line r of screen v. The screen below this
  764.  * line is scrolled up, and the bottom line is cleared.
  765.  */
  766.  
  767. #define scroll(v) delete_line(v, 0)
  768.  
  769. INLINE static void
  770. delete_line(v, r)
  771.     SCREEN *v;
  772.     int r;
  773. {
  774.     long *src, *dst, nbytes;
  775.  
  776.     if (r == 0) {
  777.         if (hardbase) {
  778.             hardware_scroll(v);
  779.             clrline(v, v->maxy);
  780.             return;
  781.         }
  782.         nbytes = scrnsize - v->linelen;
  783.     }
  784.     else
  785.         nbytes = (long)v->linelen * (v->maxy - r);
  786.  
  787.     /* Sheeze, how many times do we really have to cast... 
  788.        Erling.    
  789.     */
  790.  
  791.     dst = (long *)(base + ((long)r * v->linelen));
  792.     src = (long *)( ((long)dst) + v->linelen);
  793.  
  794.     quickmove(dst, src, nbytes);
  795.  
  796. /* clear the last line */
  797.     clrline(v, v->maxy);
  798. }
  799.  
  800. /*
  801.  * insert_line(v, r): scroll all of the screen starting at line r down,
  802.  * and then clear line r.
  803.  */
  804.  
  805. INLINE static void
  806. insert_line(v, r)
  807.     SCREEN *v;
  808.     int r;
  809. {
  810.     long *src, *dst;
  811.     int i, limit;
  812.  
  813.     limit = v->maxy;
  814.     for (i = limit-1; i >= r ; --i) {
  815.     /* move line i to line i+1 */
  816.     /* AND do some casting to support big screens.
  817.        Erling
  818.     */
  819.         src = (long *)(base + ((long)i * v->linelen));
  820.         dst = (long *)(base + ((i+1)*(long)v->linelen));
  821.         quickmove(dst, src, v->linelen);
  822.     }
  823.  
  824. /* clear line r */
  825.     clrline(v, r);
  826. }
  827.  
  828. /*
  829.  * special states for handling ESC b x and ESC c x. Note that for now,
  830.  * color is ignored.
  831.  */
  832.  
  833. static void
  834. setbgcol(v, c)
  835.     SCREEN *v;
  836.     int c;
  837. {
  838.     int i;
  839.  
  840.     v->bgcol = c & ((1 << v->planes)-1);
  841.     for (i = 0; i < v->planes; i++)
  842.         bgmask[i] = (v->bgcol & (1 << i)) ? -1 : 0;
  843.     state = normal_putch;
  844. }
  845.  
  846. static void
  847. setfgcol(v, c)
  848.     SCREEN *v;
  849.     int c;
  850. {
  851.     int i;
  852.  
  853.     v->fgcol = c & ((1 << v->planes)-1);
  854.     for (i = 0; i < v->planes; i++)
  855.         fgmask[i] = (v->fgcol & (1 << i)) ? -1 : 0;
  856.     state = normal_putch;
  857. }
  858.  
  859. static void
  860. quote_putch(v, c)
  861.     SCREEN *v;
  862.     int c;
  863. {
  864.     (*vpaint)(v, c, v->cursaddr);
  865.     state = normal_putch;
  866.     v->cx++;
  867.     if (v->cx > v->maxx) {
  868.         if (v->flags & FWRAP) {
  869.             v->cx = 0;
  870.             normal_putch(v, '\n');
  871.             v->cursaddr = PLACE(v, v->cx, v->cy);
  872.         } else {
  873.             v->cx = v->maxx;
  874.         }
  875.     } else {
  876. #if 0
  877.         v->cursaddr = PLACE(v, v->cx, v->cy);
  878. #else
  879.         v->cursaddr++;
  880.         if ( (v->cx & 1) == 0 && v->planes > 1) { /* new word */
  881.             short skipwords = v->planes - 1;
  882.             v->cursaddr += skipwords+skipwords;
  883.         }
  884. #endif
  885.     }
  886. }
  887.  
  888. /*
  889.  * putesc(v, c): handle the control sequence ESC c
  890.  */
  891.  
  892. static void
  893. putesc(v, c)
  894.     SCREEN *v;
  895.     int c;
  896. {
  897.     int cx, cy;
  898.  
  899.     cx = v->cx; cy = v->cy;
  900.  
  901.     switch (c) {
  902.     case 'A':        /* cursor up */
  903.         gotoxy(v, cx, cy-1);
  904.         break;
  905.     case 'B':        /* cursor down */
  906.         gotoxy(v, cx, cy+1);
  907.         break;
  908.     case 'C':        /* cursor right */
  909.         gotoxy(v, cx+1, cy);
  910.         break;
  911.     case 'D':        /* cursor left */
  912.         gotoxy(v, cx-1, cy);
  913.         break;
  914.     case 'E':        /* clear home */
  915.         clear(v);
  916.         /* fall through... */
  917.     case 'H':        /* cursor home */
  918.         gotoxy(v, 0, 0);
  919.         break;
  920.     case 'I':        /* cursor up, insert line */
  921.         if (cy == 0) {
  922.             insert_line(v, 0);
  923.         }
  924.         else
  925.             gotoxy(v, cx, cy-1);
  926.         break;
  927.     case 'J':        /* clear below cursor */
  928.         clrfrom(v, cx, cy, v->maxx, v->maxy);
  929.         break;
  930.     case 'K':        /* clear remainder of line */
  931.         clrfrom(v, cx, cy, v->maxx, cy);
  932.         break;
  933.     case 'L':        /* insert a line */
  934.         gotoxy(v, 0, cy);
  935.         insert_line(v, cy);
  936.         break;
  937.     case 'M':        /* delete line */
  938.         gotoxy(v, 0, cy);
  939.         delete_line(v, cy);
  940.         break;
  941.     case 'Q':        /* quote-next-char */
  942.         state = quote_putch;
  943.         return;
  944.     case 'Y':
  945.         state = escy_putch;
  946.         return;        /* YES, this should be 'return' */
  947.  
  948.     case 'b':
  949.         state = setfgcol;
  950.         return;
  951.     case 'c':
  952.         state = setbgcol;
  953.         return;
  954.     case 'd':        /* clear to cursor position */
  955.         clrfrom(v, 0, 0, cx, cy);
  956.         break;
  957.     case 'e':        /* enable cursor */
  958.         v->flags |= CURS_ON;
  959.         v->hidecnt = 1;    /* so --v->hidecnt shows the cursor */
  960.         break;
  961.     case 'f':        /* cursor off */
  962.         v->hidecnt++;
  963.         v->flags &= ~CURS_ON;
  964.         break;
  965.     case 'j':        /* save cursor position */
  966.         v->savex = v->cx;
  967.         v->savey = v->cy;
  968.         break;
  969.     case 'k':        /* restore saved position */
  970.         gotoxy(v, v->savex, v->savey);
  971.         break;
  972.     case 'l':        /* clear line */
  973.         gotoxy(v, 0, cy);
  974.         clrline(v, cy);
  975.         break;
  976.     case 'o':        /* clear from start of line to cursor */
  977.         clrfrom(v, 0, cy, cx, cy);
  978.         break;
  979.     case 'p':        /* reverse video on */
  980.         v->flags |= FINVERSE;
  981.         break;
  982.     case 'q':        /* reverse video off */
  983.         v->flags &= ~FINVERSE;
  984.         break;
  985.     case 'v':        /* wrap on */
  986.         v->flags |= FWRAP;
  987.         break;
  988.     case 'w':
  989.         v->flags &= ~FWRAP;
  990.         break;
  991.     }
  992.     state = normal_putch;
  993. }
  994.  
  995. /*
  996.  * escy1_putch(v, c): for when an ESC Y + char has been seen
  997.  */
  998. static void
  999. escy1_putch(v, c)
  1000.     SCREEN *v;
  1001.     int c;
  1002. {
  1003.     gotoxy(v, c - ' ', escy1 - ' ');
  1004.     state = normal_putch;
  1005. }
  1006.  
  1007. /*
  1008.  * escy_putch(v, c): for when an ESC Y has been seen
  1009.  */
  1010. static void
  1011. escy_putch(v, c)
  1012.     SCREEN *v;
  1013.     int c;
  1014. {
  1015.     UNUSED(v);
  1016.     escy1 = c;
  1017.     state = escy1_putch;
  1018. }
  1019.  
  1020. /*
  1021.  * normal_putch(v, c): put character 'c' on screen 'v'. This is the default
  1022.  * for when no escape, etc. is active
  1023.  */
  1024.  
  1025. static void
  1026. normal_putch(v, c)
  1027.     SCREEN *v;
  1028.     int c;
  1029. {
  1030. /* control characters */
  1031.     if (c < ' ') {
  1032.         switch (c) {
  1033.         case '\r':
  1034.             gotoxy(v, 0, v->cy);
  1035.             return;
  1036.         case '\n':
  1037.             if (v->cy == v->maxy) {
  1038.                 scroll(v);
  1039.             }
  1040.             else
  1041.                 gotoxy(v, v->cx, v->cy+1);
  1042.             return;
  1043.         case '\b':
  1044.             gotoxy(v, v->cx-1, v->cy);
  1045.             return;
  1046.         case '\007':        /* BELL */
  1047.             (void)bconout(CONDEV, 7);
  1048.             return;
  1049.         case '\033':        /* ESC */
  1050.             state = putesc;
  1051.             return;
  1052.         case '\t':
  1053.             gotoxy(v, (v->cx + 8) & ~7, v->cy);
  1054.             return;
  1055.         default:
  1056.             return;
  1057.         }
  1058.     }
  1059.  
  1060.     (*vpaint)(v, c, v->cursaddr);
  1061.     v->cx++;
  1062.     if (v->cx > v->maxx) {
  1063.         if (v->flags & FWRAP) {
  1064.             v->cx = 0;
  1065.             normal_putch(v, '\n');
  1066.             v->cursaddr = PLACE(v, v->cx, v->cy);
  1067.         } else {
  1068.             v->cx = v->maxx;
  1069.         }
  1070.     } else {
  1071. #if 0
  1072.         v->cursaddr = PLACE(v, v->cx, v->cy);
  1073. #else
  1074.         v->cursaddr++;
  1075.         if ( (v->cx & 1) == 0 && v->planes > 1) { /* new word */
  1076.             short skipwords = v->planes - 1;
  1077.             v->cursaddr += skipwords+skipwords;
  1078.         }
  1079. #endif
  1080.     }
  1081. }
  1082.  
  1083. INLINE static void
  1084. put_ch(v, c)
  1085.     SCREEN *v;
  1086.     int c;
  1087. {
  1088.     (*state)(v, c & 0x00ff);
  1089. }
  1090.  
  1091. static long ARGS_ON_STACK screen_open    P_((FILEPTR *f));
  1092. static long ARGS_ON_STACK screen_read    P_((FILEPTR *f, char *buf, long nbytes));
  1093. static long ARGS_ON_STACK screen_write P_((FILEPTR *f, const char *buf, long nbytes));
  1094. static long ARGS_ON_STACK screen_lseek P_((FILEPTR *f, long where, int whence));
  1095. static long ARGS_ON_STACK screen_ioctl P_((FILEPTR *f, int mode, void *buf));
  1096. static long ARGS_ON_STACK screen_close P_((FILEPTR *f, int pid));
  1097. static long ARGS_ON_STACK screen_select P_((FILEPTR *f, long p, int mode));
  1098. static void ARGS_ON_STACK screen_unselect P_((FILEPTR *f, long p, int mode));
  1099.  
  1100. extern long    ARGS_ON_STACK null_datime    P_((FILEPTR *f, short *time, int rwflag));
  1101.  
  1102. DEVDRV screen_device = {
  1103.     screen_open, screen_write, screen_read, screen_lseek, screen_ioctl,
  1104.     null_datime, screen_close, screen_select, screen_unselect
  1105. };
  1106.  
  1107. static long ARGS_ON_STACK 
  1108. screen_open(f)
  1109.     FILEPTR *f;
  1110. {
  1111.  
  1112.     if (!current) {
  1113.         init();
  1114.     } else
  1115.         return EACCDN;        /* screen in use */
  1116.  
  1117.     f->flags |= O_TTY;
  1118.     return 0;
  1119. }
  1120.  
  1121. static long ARGS_ON_STACK 
  1122. screen_close(f, pid)
  1123.     FILEPTR *f;
  1124.     int pid;
  1125. {
  1126.     UNUSED(pid);
  1127.  
  1128.     if (f->links <= 0) {
  1129.         if (hardbase) {
  1130.             quickmove(oldbase, base, scrnsize);
  1131.             base = oldbase;
  1132.             Setscreen(oldbase, oldbase, -1);
  1133.         }
  1134.         current = 0;
  1135.     }
  1136.     return 0;
  1137. }
  1138.  
  1139. static long ARGS_ON_STACK 
  1140. screen_write(f, buf, bytes)
  1141.     FILEPTR *f; const char *buf; long bytes;
  1142. {
  1143.     SCREEN *v = current;
  1144.     long *r;
  1145.     long ret = 0;
  1146.     int c;
  1147.  
  1148.     UNUSED(f);
  1149.  
  1150.     (void)checkkeys();
  1151.     v->hidecnt++;
  1152.     v->flags |= CURS_UPD;        /* for TOS 1.0 */
  1153.     curs_off(v);
  1154.     r = (long *)buf;
  1155.     while (bytes > 0) {
  1156.         c = (int) *r++;
  1157.         put_ch(v, c);
  1158.         bytes -= 4; ret+= 4;
  1159.     }
  1160.     if (v->hidecnt > 0)
  1161.         --v->hidecnt;
  1162.     else
  1163.         v->hidecnt = 0;
  1164.     curs_on(v);
  1165.     v->flags &= ~CURS_UPD;
  1166.     return ret;
  1167. }
  1168.  
  1169. static long ARGS_ON_STACK 
  1170. screen_read(f, buf, bytes)
  1171.     FILEPTR *f; char *buf; long bytes;
  1172. {
  1173.     long *r, ret = 0;
  1174.  
  1175.     r = (long *)buf;
  1176.  
  1177.     while (bytes > 0) {
  1178.         if ( (f->flags & O_NDELAY) && !bconstat(CONDEV) )
  1179.             break;
  1180.         *r++ = bconin(CONDEV) & 0x7fffffffL;
  1181.         bytes -= 4; ret += 4;
  1182.     }
  1183.     return ret;
  1184. }
  1185.  
  1186. static long ARGS_ON_STACK 
  1187. screen_lseek(f, where, whence)
  1188.     FILEPTR *f;
  1189.     long where;
  1190.     int whence;
  1191. {
  1192. /* terminals always are at position 0 */
  1193.     UNUSED(f); UNUSED(where);
  1194.     UNUSED(whence);
  1195.     return 0;
  1196. }
  1197.  
  1198. static long ARGS_ON_STACK 
  1199. screen_ioctl(f, mode, buf)
  1200.     FILEPTR *f; int mode; void *buf;
  1201. {
  1202.     long *r = (long *)buf;
  1203.     struct winsize *w;
  1204.  
  1205.     UNUSED(f);
  1206.  
  1207.     if (mode == FIONREAD) {
  1208.         if (bconstat(CONDEV))
  1209.             *r = 1;
  1210.         else
  1211.             *r = 0;
  1212.     }
  1213.     else if (mode == FIONWRITE) {
  1214.             *r = 1;
  1215.     }
  1216.     else if (mode == TIOCFLUSH) {
  1217. /* BUG: this should flush the input/output buffers */
  1218.         return 0;
  1219.     }
  1220.     else if (mode == TIOCGWINSZ) {
  1221.         w = (struct winsize *)buf;
  1222.         w->ws_row = current->maxy+1;
  1223.         w->ws_col = current->maxx+1;
  1224.     }
  1225.     else if (mode >= TCURSOFF && mode <= TCURSGRATE) {
  1226.         SCREEN *v = current;
  1227.         switch(mode) {
  1228.         case TCURSOFF:
  1229.             curs_off(v);
  1230.             v->hidecnt++;
  1231.             v->flags &= ~CURS_ON;
  1232.             break;
  1233.         case TCURSON:
  1234.             v->flags |= CURS_ON;
  1235.             v->hidecnt = 0;
  1236.             curs_on(v);
  1237.             break;
  1238.         case TCURSBLINK:
  1239.             curs_off(v);
  1240.             v->flags |= CURS_FLASH;
  1241.             curs_on(v);
  1242.             break;
  1243.         case TCURSSTEADY:
  1244.             curs_off(v);
  1245.             v->flags &= ~CURS_FLASH;
  1246.             curs_on(v);
  1247.             break;
  1248.         case TCURSSRATE:
  1249.             v->period = *((short *)buf);
  1250.             break;
  1251.         case TCURSGRATE:
  1252.             return v->period;
  1253.         }
  1254.     } else
  1255.         return EINVFN;
  1256.  
  1257.     return 0;
  1258. }
  1259.  
  1260. static long ARGS_ON_STACK 
  1261. screen_select(f, p, mode)
  1262.     FILEPTR *f; long p; int mode;
  1263. {
  1264.     struct tty *tty = (struct tty *)f->devinfo;
  1265.     int dev = CONDEV;
  1266.  
  1267.     if (mode == O_RDONLY) {
  1268.         if (bconstat(dev)) {
  1269.             return 1;
  1270.         }
  1271.         if (tty) {
  1272.         /* avoid collisions with other processes */
  1273.             if (!tty->rsel)
  1274.                 tty->rsel = p;
  1275.         }
  1276.         return 0;
  1277.     } else if (mode == O_WRONLY) {
  1278.         return 1;
  1279.     }
  1280.     /* default -- we don't know this mode, return 0 */
  1281.     return 0;
  1282. }
  1283.  
  1284. static void ARGS_ON_STACK 
  1285. screen_unselect(f, p, mode)
  1286.     FILEPTR *f;
  1287.     long p;
  1288.     int mode;
  1289. {
  1290.     struct tty *tty = (struct tty *)f->devinfo;
  1291.  
  1292.     if (tty) {
  1293.         if (mode == O_RDONLY && tty->rsel == p)
  1294.             tty->rsel = 0;
  1295.         else if (mode == O_WRONLY && tty->wsel == p)
  1296.             tty->wsel = 0;
  1297.     }
  1298. }
  1299.  
  1300. #endif /* FASTTEXT */
  1301.